package org.fight.net.handler;

import java.util.Map;

import org.fight.actor.ActorMsg;
import org.fight.actor.ActorMsgTypeEnum;
import org.fight.cache.SessionCache;
import org.fight.net.KcpConstant;

import com.google.common.collect.Maps;
import com.sojoys.artifact.factory.session.ISession;
import com.sojoys.artifact.manager.SessionManager;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;

import akka.actor.ActorRef;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;

/**
 * 数据包处理器
 * @author win7
 *
 */
public class KcpHandler extends SimpleChannelInboundHandler<DatagramPacket> {
	
	static final Log log = LogFactory.get(KcpHandler.class);
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
		ByteBuf buf = msg.content();
    	buf.markReaderIndex();
    	if (buf == null || buf.readableBytes() < 24) {
            return;
        }
    	// 提取会话标识
    	int conv = buf.readInt();
    	buf.resetReaderIndex();
    	
    	Map<String, Object> map = Maps.newHashMap();
		map.put(KcpConstant.CONV, conv);
		map.put(KcpConstant.SOCKET_CHANNEL, ctx.channel());
		map.put(KcpConstant.TARGET_ADDRESS, msg.sender());
		
    	ISession session = SessionCache.me().getSession(conv);
    	if (session == null) {
    		session = SessionManager.me().createSession(map);
    		log.debug("-> 新连接 PlayerId:{} Address:{}",conv,msg.sender());
		}else {
			if (!msg.sender().equals(session.getAttr(KcpConstant.TARGET_ADDRESS))) {
				log.debug("-> 重连接 PlayerId:{} OldAddress:{} NewAddress:{}",conv,session.getAttr(KcpConstant.TARGET_ADDRESS),msg.sender());
				session.close();
	    		session = SessionManager.me().createSession(map);
			}
		}
		// 此处因为使用的堆外内存,所有不能直接调用array
		byte[] data = new byte[buf.readableBytes()];
		buf.readBytes(data);
		
		// 使用Actor接收消息
		ActorRef actor = session.getAttr(KcpConstant.ACTOR);
		actor.tell(new ActorMsg(ActorMsgTypeEnum.NETTY, data), ActorRef.noSender());
		
	}
}
